<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
  <div id="app">
    <div v-if="isShow">
      <p><input type="text" v-model="name" placeholder="请输入昵称"></p>
      <p><input type="text" v-model="roomid" placeholder="请输入房间号"></p>
      <button type="button" @click="enter">进入聊天室</button>
    </div>
    <div v-else>
      <ul>
        <li v-for="(item,index) in lists" :key="'message' +index">{{item}}</li>
        <li>在线人数：{{num}}</li>
      </ul>
      <input type="text" v-model="message">
      <button type="button" @click="send">发送</button>
      <button type="button" @click="close">退出聊天室</button>
    </div>
  </div>

  <script>
    var app = new Vue({
      el: '#app',
      data: {
        message: '',
        lists: [],
        ws: {},
        name: '',
        num: 0,
        roomid: '',
        isShow: true,
        handle: {}
      },
      mounted() {

      },
      methods: {
        init: function () {
          this.ws = new WebSocket('ws:127.0.0.1:3000')
          this.ws.onopen = this.onOpen
          this.ws.onmessage = this.onMessage
          this.ws.onclose = this.onClose
          this.ws.onerror = this.onError
        },
        onOpen: function () {
          this.ws.send(JSON.stringify({
            event: 'auth',
            message: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o'
          }))
          console.log('连接服务端成功');
          //不能直接发送对象，event却别用户在发送信息还是昵称
          this.ws.send(JSON.stringify({
            event: 'enter',
            message: this.name,
            roomid: this.roomid
          }))
        },
        onMessage: function (event) {
          //不接受历史消息
          if (this.isShow) {
            return
          }
          var obj = JSON.parse(event.data)
          switch (obj.event) {
            //鉴权失败，跳转路由
            case 'noauth':
              break
            case 'enter':
              this.lists.push('欢迎：' + obj.message + '加入聊天室')
              break
            case 'out':
              this.lists.push(obj.name + '已经退出聊天室')
              break
            //心跳检测返回
            case 'heartbeat':
              this.cheackServer()//断线重连
              this.ws.send(JSON.stringify({
                event: 'heartbeat',
                message: 'pong'
              }))
              break
            default:
              //自己不给自己发信息
              if (obj.name !== this.name) {
                this.lists.push(obj.name + '：' + obj.message)
              }
          }
          this.num = obj.num
        },
        onClose: function () {
          console.log('连接断开，退出聊天');
          this.ws.close()
        },
        onError: function () {
          console.log('连接异常');
          //连接失败后进行断线重连
          var _this = this
          setTimeout(function () {
            _this.init()
          }, 1000)
        },
        //发送信息
        send: function () {
          if (this.ws.readyState === 1) {
            this.lists.push(this.name + '：' + this.message)
            //不能直接发送对象，event却别用户在发送信息还是昵称
            this.ws.send(JSON.stringify({
              event: 'message',
              message: this.message,
              name: this.name
            }))
            this.message = ''
          } else {
            alert('连接断开，不能发送消息')
            return
          }

        },
        //关闭
        close: function () {
          this.ws.close()
        },
        //输入昵称
        enter: function () {
          if (this.name.trim() === '') {
            alert('用户名不得为空')
            return
          }
          this.init()
          this.isShow = false
        },
        //这一个是心跳检测的重连
        cheackServer: function () {
          var _this = this
          clearTimeout(this.handle)
          this.handle = setTimeout(function () {
            _this.onClose()
            setTimeout(function () {
              _this.init()
            }, 1000)
          }, 1000 + 500)//这里1000是心跳检测时间，500是网络延时
        }
      }
    })
  </script>
</body>

</html>